package menu;

import java.awt.Point;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JOptionPane;

import chess.BishopPiece;
import chess.ChessPiece;
import chess.KingPiece;
import chess.KnightPiece;
import chess.PawnPiece;
import chess.QueenPiece;
import chess.RookPiece;
import chess.SpecialMoveType;
import chess.SpecialMove;
import chesskers.Driver;
import chesskers.GamePiece;
import chesskers.ImagePanel;
import chesskers.UIManager;

public class ChessDisplayPanel extends GameDisplayPanel {

	List<SpecialMove> availableSpecialMoves;

	public ChessDisplayPanel() {
		super();

		if (state.isLoaded == false) {
			state.board[0][0] = new RookPiece(true, 0, 0);
			state.board[1][0] = new KnightPiece(true, 1, 0);
			state.board[2][0] = new BishopPiece(true, 2, 0);
			state.board[3][0] = new KingPiece(true, 3, 0);
			state.board[4][0] = new QueenPiece(true, 4, 0);
			state.board[5][0] = new BishopPiece(true, 5, 0);
			state.board[6][0] = new KnightPiece(true, 6, 0);
			state.board[7][0] = new RookPiece(true, 7, 0);
			state.board[0][1] = new PawnPiece(true, 0, 1);
			state.board[1][1] = new PawnPiece(true, 1, 1);
			state.board[2][1] = new PawnPiece(true, 2, 1);
			state.board[3][1] = new PawnPiece(true, 3, 1);
			state.board[4][1] = new PawnPiece(true, 4, 1);
			state.board[5][1] = new PawnPiece(true, 5, 1);
			state.board[6][1] = new PawnPiece(true, 6, 1);
			state.board[7][1] = new PawnPiece(true, 7, 1);

			state.board[0][6] = new PawnPiece(false, 0, 6);
			state.board[1][6] = new PawnPiece(false, 1, 6);
			state.board[2][6] = new PawnPiece(false, 2, 6);
			state.board[3][6] = new PawnPiece(false, 3, 6);
			state.board[4][6] = new PawnPiece(false, 4, 6);
			state.board[5][6] = new PawnPiece(false, 5, 6);
			state.board[6][6] = new PawnPiece(false, 6, 6);
			state.board[7][6] = new PawnPiece(false, 7, 6);
			state.board[0][7] = new RookPiece(false, 0, 7);
			state.board[1][7] = new KnightPiece(false, 1, 7);
			state.board[2][7] = new BishopPiece(false, 2, 7);
			state.board[3][7] = new KingPiece(false, 3, 7);
			state.board[4][7] = new QueenPiece(false, 4, 7);
			state.board[5][7] = new BishopPiece(false, 5, 7);
			state.board[6][7] = new KnightPiece(false, 6, 7);
			state.board[7][7] = new RookPiece(false, 7, 7);
		}
//		 state.board[0][0] = new QueenPiece(true, 0, 0);
//		 state.board[3][0] = new QueenPiece(true, 3, 0);
//		 state.board[7][0] = new QueenPiece(true, 7, 0);
//		 state.board[0][3] = new QueenPiece(true, 0, 3);
//		 state.board[7][3] = new QueenPiece(true, 7, 3);
//		 state.board[0][7] = new QueenPiece(true, 0, 7);
//		 state.board[3][7] = new QueenPiece(true, 3, 7);
//		 state.board[7][7] = new QueenPiece(true, 7, 7);
//		
//		 state.board[3][3] = new KingPiece(false, 3, 3);

		availableSpecialMoves = new ArrayList<SpecialMove>();
		RedrawBoard();
	}

	public void InstantiateBackground() {
		gd_back_manPanel = new ImagePanel(new ImageIcon(
				"img/chess_background.png").getImage());
	}

	@Override
	public void MouseClickedBoard(MouseEvent e) {
		super.MouseClickedBoard(e);
		LookForSpecial();
		TestForCheckMate();
	}

	@Override
	public void RedrawBoard() {
		super.RedrawBoard();
		for (SpecialMove sm : availableSpecialMoves) {
			if (sm.isActive())
				gd_back_manPanel.AddImage(
						new ImageIcon("img/special.png").getImage(), xOffset
								+ (sm.getSelect().x * squareSize), yOffset
								+ (sm.getSelect().y * squareSize));
		}
	}

	public void GivePoints(boolean winnerBlack, boolean forfeight) {
		if (winnerBlack) {
			state.player2.chessWin++;
			if (forfeight) {
				state.player1.chessForfeit++;
			} else {
				state.player1.chessLost++;
			}
		} else {
			state.player1.chessWin++;
			if (forfeight) {
				state.player2.chessForfeit++;
			} else {
				state.player2.chessLost++;
			}
		}
		state.UpdateProfiles();
	}

	public void Tie() {
		JOptionPane.showMessageDialog(this, "Tie!");
		state.player1.chessTie++;
		state.player2.chessTie++;
		EndGame();
	}

	@Override
	public void ClickSquare(int x, int y) {
		super.ClickSquare(x, y);
		if (availableSpecialMoves.size() > 0) {
			for (SpecialMove sm : availableSpecialMoves) {
				if (((ChessPiece) state.board[sm.getStart().x][sm.getStart().y]).canSpecialMove
						&& sm.getSelect().equals(new Point(x, y))
						&& state.board[sm.getStart().x][sm.getStart().y].isBlack == state.blackGoing) {
					availableSpecialMoves = new ArrayList<SpecialMove>();
					state.board = ((ChessPiece) state.board[state.selectedX][state.selectedY])
							.SpecialMove(state.board, sm);
					if (sm.getType().equals(SpecialMoveType.move)) {
						state.board[sm.getStart().x][sm.getStart().y].moveTo(
								sm.getEnd().x, sm.getEnd().y, state.board);
						state.board[sm.getPair().x][sm.getPair().y].moveTo(
								sm.getStart().x, sm.getStart().y, state.board);
					}
					if (sm.getType().equals(SpecialMoveType.attack)) {
						state.board[sm.getStart().x][sm.getStart().y].attackTo(
								sm.getPair().x, sm.getPair().y, state.board);
						state.board[sm.getStart().x][sm.getStart().y].moveTo(
								sm.getEnd().x, sm.getEnd().y, state.board);
					}
					if (sm.getType().equals(SpecialMoveType.promote)) {
						String string = JOptionPane
								.showInputDialog("Please select a piece");
						System.out.println();
					}
					state.moveTo = new ArrayList<Point>();
					state.attackTo = new ArrayList<Point>();
					availableSpecialMoves = new ArrayList<SpecialMove>();

					if (!sm.getType().equals(SpecialMoveType.none)) {
						state.selectedX = -1;
						state.selectedY = -1;

						state.blackGoing = !state.blackGoing;
						RedrawBoard();
					}
				}
			}
		} else if (state.board[x][y] != null) {
			availableSpecialMoves = state.board[x][y]
					.getSpecialMovePossibilities();
		}

		if (state.selectedX != -1
				&& state.selectedY != -1
				&& state.board[state.selectedX][state.selectedY].getName()
						.equals("king")
				&& state.board[state.selectedX][state.selectedY].isBlack == state.blackGoing) {

			ArrayList<Point> spareMove = new ArrayList<Point>(state.moveTo);
			for (Point p : spareMove) {
				GamePiece[][] spare = new GamePiece[8][8];
				for (int i = 0; i < 8; i++) {
					for (int j = 0; j < 8; j++) {
						spare[i][j] = state.board[i][j];
					}
				}
				spare[p.x][p.y] = state.board[state.selectedX][state.selectedY];
				if (InTrouble(new Point(p.x, p.y),
						state.board[state.selectedX][state.selectedY].isBlack,
						spare)) {
					state.moveTo.remove(p);
				}
			}

			ArrayList<Point> spareAttack = new ArrayList<Point>(state.attackTo);
			for (Point p : spareAttack) {
				GamePiece[][] spare = new GamePiece[8][8];
				for (int i = 0; i < 8; i++) {
					for (int j = 0; j < 8; j++) {
						spare[i][j] = state.board[i][j];
					}
				}
				spare[p.x][p.y] = state.board[state.selectedX][state.selectedY];
				if (InTrouble(new Point(p.x, p.y),
						state.board[state.selectedX][state.selectedY].isBlack,
						spare)) {
					state.attackTo.remove(p);
				}
			}
		}

		RedrawBoard();
	}

	private void LookForSpecial() {
		if (state.blackGoing) {
			//Castling Testing
			boolean blackkingcastletest = state.board[3][0] != null
					&& state.board[3][0].getName().toLowerCase().equals("king")
					&& state.board[3][0].isUnmoved && state.board[3][0].isBlack;
			boolean blackrookleftcastletest = state.board[0][0] != null
					&& state.board[0][0].getName().toLowerCase().equals("rook")
					&& state.board[0][0].isUnmoved && state.board[0][0].isBlack;
			boolean blackleftcastletest = state.board[1][0] != null
					&& state.board[1][0] == null && state.board[2][0] == null;
			boolean blackrookrightcastletest = state.board[7][0] != null
					&& state.board[7][0].getName().toLowerCase().equals("rook")
					&& state.board[7][0].isUnmoved && state.board[7][0].isBlack;
			boolean blackrightcastletest = state.board[4][0] != null
					&& state.board[4][0] == null && state.board[5][0] == null
					&& state.board[6][0] == null;
			if (blackkingcastletest && blackrookleftcastletest
					&& blackleftcastletest) {
				((KingPiece) state.board[3][0]).canLeftCastle = true;
				((RookPiece) state.board[0][0]).canLeftCastle = true;
			}
			if (blackkingcastletest && blackrookrightcastletest
					&& blackrightcastletest) {
				((KingPiece) state.board[3][0]).canLeftCastle = true;
				((RookPiece) state.board[7][0]).canLeftCastle = true;
			}

			//En passante
			for (int i = 0; i < 8; i++) {
				for (int j = 0; j < 8; j++) {
					if (i == 0) {
						boolean t0 = state.board[i][j] != null
								&& state.board[i][j].getName().toLowerCase().equals("pawn")
								&& state.board[i][j].isBlack;
						boolean t1 = state.board[i+1][j] != null
								&& state.board[i+1][j].getName().toLowerCase().equals("pawn")
								&& !state.board[i+1][j].isBlack;
						if (t0 && t1) {
							((PawnPiece)state.board[i][j]).canRightEnpassante = true;
						}
					} else if (i == 7) {
						boolean t0 = state.board[i][j] != null
								&& state.board[i][j].getName().toLowerCase().equals("pawn")
								&& state.board[i][j].isBlack;
						boolean t2 = state.board[i-1][j] != null
								&& state.board[i-1][j].getName().toLowerCase().equals("pawn")
								&& !state.board[i-1][j].isBlack;
						if (t0 && t2) {
							((PawnPiece)state.board[i][j]).canLeftEnpassante = true;
						}
					} else {
						boolean t0 = state.board[i][j] != null
								&& state.board[i][j].getName().toLowerCase().equals("pawn")
								&& state.board[i][j].isBlack;
						boolean t1 = state.board[i+1][j] != null
								&& state.board[i+1][j].getName().toLowerCase().equals("pawn")
								&& !state.board[i+1][j].isBlack;
						boolean t2 = state.board[i-1][j] != null
								&& state.board[i-1][j].getName().toLowerCase().equals("pawn")
								&& !state.board[i-1][j].isBlack;
						if (t0 && t1) {
							((PawnPiece)state.board[i][j]).canRightEnpassante = true;
						}
						if (t0 && t2) {
							((PawnPiece)state.board[i][j]).canLeftEnpassante = true;
						}
					}
				}
			}
			
			//Pawn Promotion Testing
			for (int i : new int[] { 0, 1, 2, 3, 4, 5, 6, 7 }) {
				if (state.board[i][6] != null
						&& state.board[i][6].getName().toLowerCase()
								.equals("pawn") && state.board[i][6].isBlack) {
					((PawnPiece) state.board[i][6]).canPromote = true;
				}
			}
		} else {
			//Castling Testing
			boolean whitekingcastletest = state.board[3][7] != null
					&& state.board[3][7].getName().toLowerCase().equals("king")
					&& state.board[3][7].isUnmoved
					&& !state.board[3][0].isBlack;
			boolean whiterookleftcastletest = state.board[0][7] != null
					&& state.board[0][7].getName().toLowerCase().equals("rook")
					&& state.board[0][7].isUnmoved
					&& !state.board[0][0].isBlack;
			boolean whiteleftcastletest = state.board[1][7] != null
					&& state.board[1][7] == null && state.board[2][7] == null;
			boolean whiterookrightcastletest = state.board[7][7] != null
					&& state.board[7][7].getName().toLowerCase().equals("rook")
					&& state.board[7][7].isUnmoved
					&& !state.board[7][0].isBlack;
			boolean whiterightcastletest = state.board[4][7] != null
					&& state.board[4][7] == null && state.board[5][7] == null
					&& state.board[6][7] == null;
			if (whitekingcastletest && whiterookleftcastletest
					&& whiteleftcastletest) {
				((KingPiece) state.board[3][7]).canLeftCastle = true;
				((RookPiece) state.board[0][7]).canLeftCastle = true;
			}
			if (whitekingcastletest && whiterookrightcastletest
					&& whiterightcastletest) {
				((KingPiece) state.board[3][7]).canRightCastle = true;
				((RookPiece) state.board[7][7]).canRightCastle = true;
			}

			//En passante
			for (int i = 0; i < 8; i++) {
				for (int j = 0; j < 8; j++) {
					if (i == 0) {
						boolean t0 = state.board[i][j] != null
								&& state.board[i][j].getName().toLowerCase().equals("pawn")
								&& !state.board[i][j].isBlack;
						boolean t1 = state.board[i+1][j] != null
								&& state.board[i+1][j].getName().toLowerCase().equals("pawn")
								&& state.board[i+1][j].isBlack;
						if (t0 && t1) {
							((PawnPiece)state.board[i][j]).canRightEnpassante = true;
						}
					} else if (i == 7) {
						boolean t0 = state.board[i][j] != null
								&& state.board[i][j].getName().toLowerCase().equals("pawn")
								&& !state.board[i][j].isBlack;
						boolean t2 = state.board[i-1][j] != null
								&& state.board[i-1][j].getName().toLowerCase().equals("pawn")
								&& state.board[i-1][j].isBlack;
						if (t0 && t2) {
							((PawnPiece)state.board[i][j]).canLeftEnpassante = true;
						}
					} else {
						boolean t0 = state.board[i][j] != null
								&& state.board[i][j].getName().toLowerCase().equals("pawn")
								&& !state.board[i][j].isBlack;
						boolean t1 = state.board[i+1][j] != null
								&& state.board[i+1][j].getName().toLowerCase().equals("pawn")
								&& state.board[i+1][j].isBlack;
						boolean t2 = state.board[i-1][j] != null
								&& state.board[i-1][j].getName().toLowerCase().equals("pawn")
								&& state.board[i-1][j].isBlack;
						if (t0 && t1) {
							((PawnPiece)state.board[i][j]).canRightEnpassante = true;
						}
						if (t0 && t2) {
							((PawnPiece)state.board[i][j]).canLeftEnpassante = true;
						}
					}
				}
			}
			//Pawn Promotion Testing
			for (int i : new int[] { 0, 1, 2, 3, 4, 5, 6, 7 }) {
				if (state.board[i][1] != null
						&& state.board[i][1].getName().toLowerCase()
								.equals("pawn") && !state.board[i][1].isBlack) {
					((PawnPiece) state.board[i][1]).canPromote = true;
				}
			}
		}
	}

	private void TestForCheckMate() {
		Point k = FindKing(state.blackGoing);
		ArrayList<Point> moves = state.board[k.x][k.y]
				.getMovePossibilities(state.board);
		ArrayList<Point> attacks = state.board[k.x][k.y]
				.getAttackPossibilities(state.board);

		ArrayList<Point> spareMove = new ArrayList<Point>(moves);
		for (Point p : spareMove) {
			if (InTrouble(k, state.board[k.x][k.y].isBlack, state.board)) {
				moves.remove(p);
			}
		}

		ArrayList<Point> spareAttack = new ArrayList<Point>(attacks);
		for (Point p : spareAttack) {
			if (InTrouble(k, state.board[k.x][k.y].isBlack, state.board)) {
				attacks.remove(p);
			}
		}

		if (moves.size() == 0 && attacks.size() == 0
				&& InTrouble(k, state.board[k.x][k.y].isBlack, state.board)) {
			Victory(!state.blackGoing, false);
		}
	}

	private boolean InTrouble(Point pos, boolean currentBlack,
			GamePiece[][] sampleBoard) {
		List<Point> locs = EnemyLocations(currentBlack);
		for (Point p : locs) {
			ArrayList<Point> attackables = sampleBoard[p.x][p.y]
					.getAttackPossibilities(sampleBoard);
			if (attackables.contains(pos)) {
				return true;
			}
		}
		return false;
	}

	private List<Point> EnemyLocations(boolean currentBlack) {
		ArrayList<Point> points = new ArrayList<Point>();
		for (int i = 0; i < 8; i++) {
			for (int j = 0; j < 8; j++) {
				if (state.board[i][j] != null
						&& currentBlack != state.board[i][j].isBlack) {
					points.add(new Point(i, j));
				}
			}
		}
		return points;
	}

	private Point FindKing(boolean currentBlack) {
		for (int i = 0; i < 8; i++) {
			for (int j = 0; j < 8; j++) {
				if (state.board[i][j] != null
						&& state.board[i][j].getName().toLowerCase()
								.equals("king")) {
					if (currentBlack == state.board[i][j].isBlack) {
						return new Point(i, j);
					}
				}
			}
		}
		return new Point();
	}
}